/* protocolo.c - funções auxiliares para uso do protocolo baseado em sockets UDP
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include "protocolo.h"


//funcao para retornar o tamanho do conteudo 
int getConteudoSize(Pacote *p){
   // return strlen(p->conteudo);
	return p->sizeConteudo;
}

//funcao para retornar o tipo do pacote
char getAck(Pacote *p){
	return p->ack;
}

//funcao apra retornar o numero do pacote
int getNPacote(Pacote *p){
	return p->nPacote;
}

//funçao para gerar o objeto pacote recebido pelo socket
void empacota(Pacote *p, char ack, u_short nPacote, u_short size_conteudo , char* conteudo ){
    //+1 para o \0 da string
	p->conteudo = malloc(sizeof(char)*size_conteudo +1);
	strcpy(p->conteudo,conteudo);

	p->ack = ack;
	p->nPacote = nPacote;
	p->sizeConteudo = size_conteudo;
	p->checkSum= geraCheckSum(p);
}

//funcao para converter um pacote para String
char* pacoteToString(Pacote *p){
    char *String = malloc(sizeof(char)*(getConteudoSize(p) + TAMANHO_CABECALHO_COM_CALDA +1));
	sprintf(String,"%c%05d%05d%s%05d",(p->ack),p->nPacote,p->sizeConteudo,p->conteudo,p->checkSum);
//	printf("\nPacoToString(%d/%d): %s\n",getConteudoSize(p), strlen(String), String);

    return String;
}

void stringToPacote(Pacote *p, char *String, int tamanho){
    int i; 
    char temp[2];
    temp[1] = '\0';

    char nPacote[6]="";
    char sizeConteudo[6]="";
    char checksum[6]="";

    p->ack = (char)String[0];

    for (i=1;i<=tamanho;i++){
        temp[0] = String[i];
        if (i<=5){strcat(nPacote, temp); }
        else if (i<=10){
            strcat(sizeConteudo, temp); 
            p->sizeConteudo = (u_short)atoi(sizeConteudo);
            }
        else if (i >= tamanho - 5) { strcat(checksum, temp);}
    }
    p->conteudo= malloc(sizeof(char)*getConteudoSize(p) +1);
    strcpy(p->conteudo,"");

    for (i=TAMANHO_CABECALHO_SEM_CALDA; i < tamanho - 5 ; i++){
        temp[0] = String[i];
        strcat(p->conteudo, temp);
    }

	p->nPacote = (u_short)atoi(nPacote);

	p->checkSum= (u_short)atoi(checksum);

}

//gera o codigo checkSum
u_short geraCheckSum(Pacote *p){
    register u_long sum = 0;
    int count = getConteudoSize(p) + TAMANHO_CABECALHO_SEM_CALDA;

    char *buf = malloc(sizeof(char)*(count+1));
	sprintf(buf,"%c%05d%05d%s",p->ack,p->nPacote,p->sizeConteudo,p->conteudo);

    while(count--){
        sum += *buf++;
        if (sum & 0xFFFF0000){
            sum &= 0xFFFF;
            sum++;
        }
    }
	return ~(sum & 0xFFFF);
}


//verifica a consistencia dos dados
int check(Pacote *p){
     if( p->checkSum != geraCheckSum(p) ) return 0;
     return 1;                                                                                             
}

//retorna o conteudo do pacote
char* getConteudo(Pacote *a){
	return a->conteudo;
}
